package com.zhuzi.component;

import com.alibaba.fastjson2.JSON;
import com.google.common.collect.Lists;
import com.zhuzi.common.utils.BeanListUtils;
import com.zhuzi.dto.ths.ThsNews;
import com.zhuzi.dto.weixin.TextMD;
import com.zhuzi.dto.weixin.text.NewGnStyle;
import com.zhuzi.entity.KzzAndStockEntity;
import com.zhuzi.entity.ThsNewEntity;
import com.zhuzi.entity.ths.ThsStockGnEntity;
import com.zhuzi.repository.ThsNewEntityRepository;
import com.zhuzi.repository.ThsStockGnEntityRepository;
import com.zhuzi.utils.Constant;
import com.zhuzi.utils.JsoupHttpUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.Connection;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.redisson.api.RBloomFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.stream.Collectors;

/**
 * @author 采集
 * 2022/8/2 07:58
 * 同花顺新闻采集|新增概念
 */
@Slf4j
@Component
public class ThsNewsComponent {
    private static String PREFIX_MSG = "ths_new";
    @Autowired
    ThsNewEntityRepository thsNewEntityRepository;
    @Autowired
    KzzComponent kzzComponent;
    @Resource(name = "threadPool")
    ExecutorService threadPool;
    @Resource
    ThsStockGnEntityRepository thsStockGnEntityRepository;
    @Resource
    WeixinComponent wixinComponent;

    @Resource
    private RBloomFilter rBloomFilter;

    /**
     * 解析 新闻详细信息
     */
    private static ThsNews parseNewsDetail(ThsNews thsNews) {
        try {
            Document newRoot = JsoupHttpUtils.get(thsNews.getUrl()).parse();
            Elements publicTimeEle = newRoot.select("#pubtime_baidu");
            thsNews.setPublishTime(LocalDateTime.parse(publicTimeEle.text(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));

            Elements newContentEle = newRoot.select("body > div.main-content.clearfix > div.main-fl.fl > div.main-text.atc-content");

            Elements select = newContentEle.select("p:nth-child(3)");
            //同花顺（300033）F10数据显示，2022年8月2日美迪凯（688079）新增“VR设备”概念。
            String s = StringUtils.substringAfter(select.text(), "F10数据显示，");
            String stockNm = StringUtils.substringBetween(s, "日", "（").trim();
            String stockId = StringUtils.substringBetween(s, "（", "）").trim();
            String gn = StringUtils.substringBetween(s, "“", "”");

            thsNews.setStockNm(stockNm).setStockId(stockId).setGn(gn);
            thsNews.setNewContent(newRoot.select("p:nth-child(4) > strong").text().replace("入选理由是：", ""));

        } catch (Exception e) {
        }
        return thsNews;
    }

    //11:00-11:29， 2:30-2:59
    //9-15点每隔10分钟运行一次|周一-周五11:00-11:29 2:30-2:59 2~3分钟运行
    @Scheduled(cron = "0 0/5 9-15 ? * MON-FRI")
    @Scheduled(cron = "8 0/15 15-21 * * ?")
    @Scheduled(cron = "5 1,6,9,12,14,18,21,16,28 11 ? * MON-FRI")
    @Scheduled(cron = "5 30,33,36,39,42,45,48,51,54,56,57,58 14 ? * MON-FRI")
    @PostConstruct
    public void schedul() {
        threadPool.execute(() -> {
            try {
                initNews();
            } catch (IOException e) {
                log.error(e.getMessage());
            }
        });
    }

    /* 概念变了样式了|https://img-blog.csdnimg.cn/20159d13eff94087941bb4386ab4b73f.png */
    public void initNews() throws IOException {
        log.info("新增概念提取");
        String url = "http://stock.10jqka.com.cn/gsyw_list/" + LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")) + "/";
        Connection.Response response = JsoupHttpUtils.get(url);
        Document rootDoc = response.parse();
        Elements ulLiEles = rootDoc.select(".list-con > ul:nth-child(1) > li");
        //新闻列表(同花顺的ul>li)
        CopyOnWriteArrayList<ThsNews> newList = Lists.newCopyOnWriteArrayList();
        for (Element liEle : ulLiEles) {
            Elements href = liEle.select("span:nth-child(1) > a:nth-child(1)");
            newList.add(new ThsNews(href.text(), href.attr("href")));
        }
        // 过滤只包含可转债的部分
        List<String> stockList = kzzComponent.getAll().stream().map(KzzAndStockEntity::getStockCode).collect(Collectors.toList());
        List<ThsNewEntity> collect = newList.stream().filter(news -> Constant.Ths.Gn.isNeedNews.apply(news.getTitle()))
                .map(ThsNewsComponent::parseNewsDetail)
                .filter(item -> stockList.contains(item.getStockId()))
                .filter(item -> rBloomFilter.add(PREFIX_MSG + item.getUrl()))
                .map(thsNews -> BeanListUtils.copyBean(thsNews, ThsNewEntity::new))
                .sorted(Comparator.comparing(ThsNewEntity::getId))
                .collect(Collectors.toList());

        if (CollectionUtils.isEmpty(collect)) {
            log.info("没有新概念");
            return;
        }
        List<String> stockIdList = collect.stream().map(ThsNewEntity::getStockId).collect(Collectors.toList());

        //这个是历史已有概念
        List<ThsStockGnEntity> stockGnList = thsStockGnEntityRepository.findByStockIdIn(stockIdList);
        ConcurrentMap<String, ThsStockGnEntity> stockHisMap = stockGnList.stream().collect(Collectors.toConcurrentMap(ThsStockGnEntity::getStockId, item -> item));
        //推送消息并存储数据库
        CompletableFuture.runAsync(() -> thsNewEntityRepository.saveAll(collect));
        //发送钉钉消息
        weixinMsg(collect, stockHisMap);

    }

    /**
     * 微信提醒
     *
     * @param newEntityList 新实体列表
     * @param stockHisMap   股票地图
     */
    private void weixinMsg(List<ThsNewEntity> newEntityList, ConcurrentMap<String, ThsStockGnEntity> stockHisMap) {
        List<NewGnStyle.GnItem> gnItemList = newEntityList.stream().map(item -> {
            NewGnStyle.GnItem gnItem = BeanListUtils.copyBean(item, NewGnStyle.GnItem::new);
            ThsStockGnEntity orDefault = stockHisMap.getOrDefault(item.getStockId(), new ThsStockGnEntity());
            gnItem.setHis(orDefault.getGn());
            return gnItem;
        }).collect(Collectors.toList());
        NewGnStyle newGnStyle = new NewGnStyle().setItemList(gnItemList);
        TextMD textMD = new TextMD().setText(new TextMD.TextItem().setContent(newGnStyle.content()).all());
        wixinComponent.sendHint(JSON.toJSONString(textMD));
    }
}
